package com.basic.technology.study.introduction.thread.juc;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        int n = 4;
        // 1 begin
        // --------------
//        CyclicBarrier barrier = new CyclicBarrier(n);
//        for (int i = 0; i < n; i++) {
//            Writer writer = new CyclicBarrierDemo().new Writer(barrier);
//            writer.start();
//        }
        // --------------
        // 1 end


        // 2 begin
        // 如果说想在所有线程写入操作完之后，进行额外的其他操作可以为CyclicBarrier提供Runnable参数：
        // 从结果可以看出，当四个线程都到达barrier状态后，会从四个线程中选择一个线程去执行Runnable。
        // --------------
//        CyclicBarrier barrier = new CyclicBarrier(n, new Runnable() {
//            @Override
//            public void run() {
//                System.out.println("当前线程"+Thread.currentThread().getName());
//            }
//        });
//        for (int i = 0; i < n; i++) {
//            Writer writer = new CyclicBarrierDemo().new Writer(barrier);
//            writer.start();
//        }
        // --------------
        // 2 end


        // 3 begin    配合 3 run
        // 故意让最后一个线程启动延迟，因为在前面三个线程都达到barrier之后，
        // 等待了指定的时间发现第四个线程还没有达到barrier，就抛出异常并继续执行后面的任务
        // --------------
//        CyclicBarrier barrier = new CyclicBarrier(n);
//
//        for (int i = 0; i < n; i++) {
//            if (i < n - 1) {
//                Writer writer = new CyclicBarrierDemo().new Writer(barrier);
//                writer.start();
//            } else {
//                try {
//                    Thread.sleep(5000);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                Writer writer = new CyclicBarrierDemo().new Writer(barrier);
//                writer.start();
//            }
//        }
        // --------------
        // 3 end

        // 4 begin
        // 故意让最后一个线程启动延迟，因为在前面三个线程都达到barrier之后，
        // 等待了指定的时间发现第四个线程还没有达到barrier，就抛出异常并继续执行后面的任务
        // --------------
        CyclicBarrier barrier = new CyclicBarrier(n);
        for (int i = 0; i < n; i++) {
            Writer writer = new CyclicBarrierDemo().new Writer(barrier);
            writer.start();
        }
        try {
            Thread.sleep(8000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println("CyclicBarrier重用");
        for (int i = 0; i < n; i++) {
            Writer writer = new CyclicBarrierDemo().new Writer(barrier);
            writer.start();
        }
        // --------------
        // 4 end

    }


    class Writer extends Thread {
        private CyclicBarrier cyclicBarrier;

        public Writer(CyclicBarrier cyclicBarrier) {
            this.cyclicBarrier = cyclicBarrier;
        }

        @Override
        public void run() {

            System.out.println("线程" + Thread.currentThread().getName() + "正在写入数据...");
            try {
                Thread.sleep(5000);
                System.out.println("线程" + Thread.currentThread().getName() + "写入数据完毕，等待其他线程写入完毕");
                cyclicBarrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
            System.out.println("所有线程写入完毕，继续处理其他任务...");

        }

        // 3
//        @Override
//        public void run() {
//
//            System.out.println("线程" + Thread.currentThread().getName() + "正在写入数据...");
//            try {
//                Thread.sleep(5000);
//                System.out.println("线程" + Thread.currentThread().getName() + "写入数据完毕，等待其他线程写入完毕");
//                try {
//                    cyclicBarrier.await(2000, TimeUnit.MILLISECONDS);
//                } catch (TimeoutException e) {
//                    System.out.println("T");
//                    e.printStackTrace();
//                }
//            } catch (InterruptedException e) {
//                System.out.println("I");
//                e.printStackTrace();
//            } catch (BrokenBarrierException e) {
//                System.out.println("B");
//                e.printStackTrace();
//            }
//            System.out.println("所有线程写入完毕，继续处理其他任务...");
//
//        }
        // 3


    }
}
